package com.company.nuwa.redis.utils;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * <p>SpEL Expression Util</p >
 *
 * @author youyoukele
 * @version 1.0
 * @date 2021/9/5
 */
public class SpelExpressionUtil {

    private static final SpelExpressionParser PARSER = new SpelExpressionParser();

    /**
     * 解析表达式，若表达式为`空`，则返回类名+方法名
     *
     * @param joinPoint        切点
     * @param expressionString SpEl 表达式
     * @return
     */
    public static String parseExpression(ProceedingJoinPoint joinPoint, String expressionString) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();

        if (StringUtils.isBlank(expressionString)) {
            return methodSignature.getMethod().getDeclaringClass().getSimpleName() + "#" + methodSignature.getMethod().getName();
        }

        Map<String, Object> paramMap = AopUtil.getParamMap(joinPoint);
        return parseExpression(expressionString, paramMap);
    }

    /**
     * 解析表达式
     *
     * @param expressionString SpEl 表达式
     * @param paramMap         参数
     * @return
     */
    public static String parseExpression(String expressionString, Map<String, Object> paramMap) {
        Expression expression = PARSER.parseExpression(expressionString);
        StandardEvaluationContext context = new StandardEvaluationContext();
        context.setVariables(paramMap);
        return Objects.requireNonNull(expression.getValue(context)).toString();
    }

    /**
     * 解析表达式
     *
     * @param expressionString SpEl 表达式
     * @param paramMap         参数
     * @return
     */
    public static List<String> parseExpressionList(String expressionString, Map<String, Object> paramMap) {
        Expression expression = PARSER.parseExpression(expressionString);
        StandardEvaluationContext context = new StandardEvaluationContext();
        context.setVariables(paramMap);
        return (List<String>)expression.getValue(context);
    }

}
